/**
 * @file app_midi_stream.c
 * @brief MIDI消息队列和数据流解析器实现
 * @version 1.0
 * @date 2025-11-04
 */

#include "app_midi_stream.h"
#include "app_midi.h"
#include "midi_parser.h"
#include "midi2_ump.h"
#include "nst_msg.h"
#include "user_config.h"
#include <string.h>

/* 私有变量定义 -------------------------------------------------------------*/

nst_msg_queue_t s_midi_queue;
uint8_t s_midi_buffer[sizeof(midi_message_t) * MIDI_QUEUE_SIZE];

/* 私有函数声明 -------------------------------------------------------------*/
static int parse_and_enqueue_stream(uint8_t *data, uint16_t len);

/* 公共函数实现 -------------------------------------------------------------*/

/**
 * @brief 初始化MIDI消息队列和流解析器
 */
int app_midi_stream_init(void)
{
    nst_msg_init(&s_midi_queue, "MIDI_RX", s_midi_buffer,
                 sizeof(midi_message_t), MIDI_QUEUE_SIZE);

    return 0;
}

/**
 * @brief 处理CAN接收到的数据流
 */
int app_midi_stream_feed(uint8_t *data, uint16_t len)
{
    if (data == NULL || len == 0)
    {
        return -1;
    }

    return parse_and_enqueue_stream(data, len);
}

/**
 * @brief 从队列中获取一条MIDI消息
 */
bool app_midi_stream_pop(midi_message_t *msg)
{
    if (msg == NULL)
    {
        return false;
    }

    return nst_msg_dequeue(&s_midi_queue, msg);
}

/**
 * @brief 获取队列中待处理消息数量
 */
uint8_t app_midi_stream_get_count(void)
{
    uint16_t count = MIDI_QUEUE_SIZE - nst_msg_remaining(&s_midi_queue) - 1;
    return (uint8_t)count;
}

/**
 * @brief 检查队列是否为空
 */
bool app_midi_stream_is_empty(void)
{
    return nst_msg_is_empty(&s_midi_queue);
}

/**
 * @brief 检查队列是否已满
 */
bool app_midi_stream_is_full(void)
{
    return nst_msg_is_full(&s_midi_queue);
}

/**
 * @brief 清空队列
 */
void app_midi_stream_clear(void)
{
    midi_message_t dummy;
    while (nst_msg_dequeue(&s_midi_queue, &dummy))
    {
        /* 清空所有消息 */
    }
}

/**
 * @brief MIDI消息处理任务 (主循环调用)
 * @note 每次仅处理1条消息，避免阻塞
 */
void app_midi_stream_process(void)
{
    midi_message_t msg;
    extern user_config_t user_config;

    /* 单条处理队列中的消息 */
    if (app_midi_stream_pop(&msg))
    {
        /* 设定模式: 只处理 NOTE ON 和 SETUP_MODE 消息 */
        if (user_config.setup_mode != 0)
        {
            if (msg.type == MIDI_MSG_NOTE_ON)
            {
                app_midi_setup_adjust(msg.velocity);  /* 用 velocity 调整参数 */
            }
            else if (msg.type == MIDI_MSG_CONTROL_CHANGE || msg.type == MIDI_MSG_SETUP_MODE)
            {
                app_midi_process_cc(msg.controller, msg.value);  /* 处理模式切换 */
            }
            return;  /* 设定模式下忽略其他消息 */
        }

        /* 播放模式: 正常处理所有消息 */
        switch (msg.type)
        {
            case MIDI_MSG_NOTE_ON:
                app_midi_note_on(msg.note, msg.velocity);
                break;

            case MIDI_MSG_NOTE_OFF:
                app_midi_note_off(msg.note);
                break;

            case MIDI_MSG_ALL_NOTES_OFF:
                app_midi_all_notes_off();
                break;

            case MIDI_MSG_CONTROL_CHANGE:
            case MIDI_MSG_SETUP_MODE:
                app_midi_process_cc(msg.controller, msg.value);
                break;

            case MIDI_MSG_TEMP_WARNING:
                /* 温度警告由主控发送，驱动板不处理 */
                break;

            default:
                /* 未知消息类型，忽略 */
                break;
        }
    }
}

/* 私有函数实现 -------------------------------------------------------------*/

/**
 * @brief 解析数据流并入队
 * @details 自动识别消息格式并拆分多个消息
 */
static int parse_and_enqueue_stream(uint8_t *data, uint16_t len)
{
    uint16_t offset = 0;
    int enqueued_count = 0;
    midi_message_t msg;

    while (offset < len)
    {
        uint16_t remaining = len - offset;
        uint8_t *ptr = &data[offset];
        int consumed = 0;  /* 本次消费的字节数 */

        /* 策略1: MIDI 1.0字节流 (优先检查,3字节) */
        if (consumed == 0 && remaining >= 3)
        {
            /* 检查状态字节 (8x/9x/Bx) */
            uint8_t status = ptr[0];
            if ((status & 0xF0) == 0x80 ||
                (status & 0xF0) == 0x90 ||
                (status & 0xF0) == 0xB0)
            {
                if (midi_parser_parse(ptr, 3, &msg) == 0)
                {
                    if (nst_msg_enqueue(&s_midi_queue, &msg))
                    {
                        enqueued_count++;
                    }
                    consumed = 3;
                }
            }
        }

        /* 策略2: 检测MIDI 2.0 UMP格式 (4字节对齐) */
        if (consumed == 0 && remaining >= 4 && (offset % 4) == 0)
        {
            /* 提取Message Type */
            uint8_t mt = (ptr[0] >> 4) & 0x0F;
            uint8_t msg_size = midi2_ump_get_size(mt);

            /* 验证是否为有效UMP消息 (MT2=64位, MT4=128位) */
            if (msg_size > 0 && remaining >= msg_size)
            {
                if (midi_parser_parse(ptr, msg_size, &msg) == 0)
                {
                    if (nst_msg_enqueue(&s_midi_queue, &msg))
                    {
                        enqueued_count++;
                    }
                    consumed = msg_size;
                }
            }
        }

        /* 无法识别的数据，跳过1字节 */
        if (consumed == 0)
        {
            offset++;
        }
        else
        {
            offset += consumed;
        }
    }

    return enqueued_count;
}

/******************************** 文件结束 *********************************/
